package appStarshipPushups.common;

/**
 * Cette classe représente plusieurs fonction utile à la logique du jeu.
 * @author Kevin Arsenault & Adam Labranche
 */
public abstract class CommonUse 
{	
	/**
	 * Ajouter un vaisseau et retourné la position du vaisseau dans la liste des vaisseaux.
	 * @return La position du vaisseau dans la liste des vaisseaux.
	 */
	public static Starship addShip(int aID)
	{
		// Ajouter le vaisseau créé au jeu.
		Starship addShip = new Starship(0, 0, 0, aID);
		Protocole.getShips().add(addShip);
		
		// Variables du vaisseau.
		boolean isValidShipPosition = false;
		
		int xPos = 0;
		int yPos = 0;
		int direction = 0;
				
		// Déterminer la coordonné du vaisseau dans l'espace.
		while(!isValidShipPosition)
		{
			// Décider la coordonnée du vaisseau.
			xPos = (int)(Math.random() * (Protocole.SCREEN_SIZE_WIDTH - Starship.SHIP_WIDTH));
			yPos = (int)(Math.random() * (Protocole.SCREEN_SIZE_HEIGHT - Starship.SHIP_HEIGHT));
			
			addShip.setPosition(xPos, yPos);
			
			// Faire une supposition si la position est valide.
			isValidShipPosition = true;
			
			// S'assurer qu'il n'occupe pas la place d'un autre vaisseau.
			for(int i = 0; i < Protocole.getShips().size(); i++)
			{
				// Si l'on analyse pas le vaisseau actuel.
				if(Protocole.getShips().get(i) != addShip)
				{
					// Si le vaisseau est à la position d'un autre.
					if(CommonUse.isCollision(addShip.getShipPlace(), Protocole.getShips().get(i).getShipPlace(), 0, 0))
					{
						isValidShipPosition = false;
					}
				}
			}
		}
		
		// Déterminer la direction au hazard.
		direction = (int)(Math.random()*Starship.DIRECTION_POSSIBILITY);
		System.out.println("Direction : " + direction);
		
		addShip.setDirection(direction);
		
		System.out.println("Ship x : " + addShip.getShipPlace().getPosition().x);
		System.out.println("Ship y : " + addShip.getShipPlace().getPosition().y);
		System.out.println("Ship x2 : " + addShip.getShipPlace().getSizePosition().x);
		System.out.println("Ship y2 : " + addShip.getShipPlace().getSizePosition().y);
		
		return addShip;
	}
	
	/**
	 * Cette fonction ajoute un laser au vaisseau spcéfié, lui attribut le
	 * numéro d'identification passé en paramètre et retourne le laser.
	 * @param aShipIndex L'index du vaisseau à utiliser.
	 * @param aID Le numéro d'identification à lui attribuer.
	 * @return Le laser ajouté.
	 */
	public static Laser addLaser(int aShipIndex, int aID)
	{		
		// Les informations concernants les dispositions du laser.
		int startX = 0;
		int startY = 0;
		int endX = 0;
		int endY = 0;
		
		int laserDirection = Protocole.getShips().get(aShipIndex).getDirection();
		System.out.println("La direction du laser : " + laserDirection);
		
		// Déterminer les coordonnées du laser par rapport à la direction de celui-ci.
		if(laserDirection == Starship.DIRECTION_DOWN)
		{
			// Les coordonnées du début du laser selon la position du vaisseau.
			startX = Protocole.getShips().get(aShipIndex).getPosition().x + (Starship.SHIP_WIDTH/2);
			startY = Protocole.getShips().get(aShipIndex).getPositionSize().y;
			
			// Les coordonnées de fin du laser selon la direction du vaisseau.
			endX = startX;
			endY = Protocole.getScreenEmplacement().getSizePosition().y;
		}
		else if(laserDirection == Starship.DIRECTION_LEFT)
		{
			// Les coordonnées du début du laser selon la position du vaisseau.
			startX = 0;
			startY = Protocole.getShips().get(aShipIndex).getPosition().y + (Starship.SHIP_HEIGHT/2);
			
			// Les coordonnées de fin du laser selon la direction du vaisseau.
			endX = Protocole.getShips().get(aShipIndex).getPosition().x;
			endY = startY;
		}
		else if(laserDirection == Starship.DIRECTION_UP)
		{
			// Les coordonnées du début du laser selon la position du vaisseau.
			startX = Protocole.getShips().get(aShipIndex).getPosition().x + (Starship.SHIP_WIDTH/2);
			startY = 0;
			
			// Les coordonnées de fin du laser selon la direction du vaisseau.
			endX = startX;
			endY = Protocole.getShips().get(aShipIndex).getPosition().y;
		}
		else if(laserDirection == Starship.DIRECTION_RIGHT)
		{
			// Les coordonnées du début du laser selon la position du vaisseau.
			startX = Protocole.getShips().get(aShipIndex).getPositionSize().x;
			startY = Protocole.getShips().get(aShipIndex).getPosition().y + (Starship.SHIP_HEIGHT/2);
			
			// Les coordonnées de fin du laser selon la direction du vaisseau.
			endX = Protocole.getScreenEmplacement().getSizePosition().x;
			endY = startY;
		}
		
		System.out.println("start X : " + startX);
		System.out.println("start Y : " + startY);
		
		// Ajouter le laser aux lasers.		
		Laser addLaser = new Laser(startX, startY, endX, endY, aID);
		System.out.println(Protocole.getLasers().size());
		Protocole.getLasers().add(addLaser);
		System.out.println(Protocole.getLasers().size());
		
		System.out.println("laser x1 : " + addLaser.getLaserEmplacement().getPosition().x);
		System.out.println("laser y1 : " + addLaser.getLaserEmplacement().getPosition().y);
		System.out.println("laser x2 : " + addLaser.getLaserEmplacement().getSizePosition().x);
		System.out.println("laser y2 : " + addLaser.getLaserEmplacement().getSizePosition().y);
		return addLaser;
	}
	
	/**
	 * Cette fonction permet de vérifier si le laser passé en paramètre a touche
	 * au vaisseau passé en paramètre.
	 * @param aLaser Le laser à utiliser dans la vérification de la collision.
	 * @param aShip Le vaisseau à utiliser dans la vérificatino de la collision.
	 * @return S'il y a eu une collision ou pas.
	 */
	public static boolean laserCollides(Laser aLaser, Starship aShip)
	{
		boolean collides = false;
				
		if(aLaser.getPosition().x < aShip.getPosition().x &&
				aLaser.getPosition().x + aLaser.getWidth()  > aShip.getPosition().x + Starship.SHIP_WIDTH &&
				aLaser.getPosition().y > aShip.getPosition().y &&
				aLaser.getPosition().y + aLaser.getHeight() < aShip.getPosition().y + Starship.SHIP_HEIGHT)
		{
			collides = true;
		}
		else if(aLaser.getPosition().x > aShip.getPosition().x &&
				aLaser.getPosition().x + aLaser.getWidth()  < aShip.getPosition().x + Starship.SHIP_WIDTH &&
				aLaser.getPosition().y < aShip.getPosition().y &&
				aLaser.getPosition().y + aLaser.getHeight() > aShip.getPosition().y + Starship.SHIP_HEIGHT)
		{
			collides = true;
		}
		
		return collides;
	}
	
	/**
	 * Détermine s'il y a collision entre deux objets.
	 * @param firstEmplacement L'emplacement du premier objet.
	 * @param secondEmplacement L'emplacement du second objet.
	 * @return S'il y a eu collision.
	 */
	public static boolean isCollision(Emplacement aFirstEmplacement, Emplacement aSecondEmplacement, int aDeltaX, int aDeltaY)
	{
		boolean isCollision = false;
		
		// Si l'un des deux espaces se touches ou s'emboite.
		if((aFirstEmplacement.getSizePosition().x + aDeltaX >= aSecondEmplacement.getPosition().x) &&
		   (aFirstEmplacement.getSizePosition().y + aDeltaY >= aSecondEmplacement.getPosition().y) &&
		   (aFirstEmplacement.getPosition().x + aDeltaX <= aSecondEmplacement.getSizePosition().x) &&
		   (aFirstEmplacement.getPosition().y + aDeltaY <= aSecondEmplacement.getSizePosition().y))
		{
			// Indiquer qu'il y a eu collision.
			isCollision = true;
		}
		
		return isCollision;
	}
	
	/**
	 * Cette fonction permet de savoir si l'objet est dans l'écran de jeu.
	 * @param aObjectEmplacement L'emplacement de l'objet.
	 * @param aScreenEmplacement L'emplacement de l'écran.
	 * @param aDeltaX Le futur déplacement en x.
	 * @param aDeltaY Le futur déplacement en y.
	 * @return Retourne vrai si l'objet est dans l'écran de jeu.
	 */
	public static boolean isInScreen(Emplacement aObjectEmplacement, Emplacement aScreenEmplacement, int aDeltaX, int aDeltaY)
	{
		boolean isInScreen = false;
		
		// Si l'objet n'est pas dans l'écran
		if((aObjectEmplacement.getPosition().x + aDeltaX >= aScreenEmplacement.getPosition().x) &&
		   (aObjectEmplacement.getPosition().y + aDeltaY >= aScreenEmplacement.getPosition().y) &&
		   (aObjectEmplacement.getSizePosition().x + aDeltaX <= aScreenEmplacement.getSizePosition().x) &&
		   (aObjectEmplacement.getSizePosition().y + aDeltaY <= aScreenEmplacement.getSizePosition().y))
		{
			// Indiquer qu'il y a eu collision.
			isInScreen = true;
			
			System.out.println("Vous êtes dans l'écran");
		}
		
		return isInScreen;
	}
	
	/**
	 * Cette fonction déplace le vaisseau passé en paramètre dans la direction
	 * demandée.
	 * @param aShipIndex L'index du vaisseau à déplacer.
	 * @param aDirection La direction vers laquelle déplacer le vaisseau.
	 * @return Retourne vrai si ça a fonctionné.
	 */
	public static boolean moveShip(int aShipIndex, String aDirection)
	{
		boolean workedWithoutError = true;
		
		// Variables servant au calcul du déplacement.
		int deltaX = 0;
		int deltaY = 0;
		int speed = Protocole.SHIP_SPEED;
		
		int newDirection = 0;
		
		// Prendre l'emplacement du vaisseau.
		Emplacement fictionEmplacement = Protocole.getShips().get(aShipIndex).getShipPlace();
		
		boolean canMove = true;
		
		// Déterminer le sens à faire bouger le vaisseau.
		if(aDirection.equals(Protocole.UP))
		{
			deltaY = -speed;
			newDirection = Starship.DIRECTION_UP;
		}
		else if(aDirection.equals(Protocole.RIGHT))
		{
			deltaX = speed;
			newDirection = Starship.DIRECTION_RIGHT;
		}
		else if(aDirection.equals(Protocole.DOWN))
		{
			deltaY = speed;
			newDirection = Starship.DIRECTION_DOWN;
		}
		else if(aDirection.equals(Protocole.LEFT))
		{
			deltaX = -speed;
			newDirection = Starship.DIRECTION_LEFT;
		}
		else // Il y a erreur dans le paramètre.
		{
			workedWithoutError = false;
		}
				
		
		// Déterminer si le vaisseau peut bouger.
		for(int i = 0; i < Protocole.getShips().size(); i++)
		{
			// Si l'on analyse pas le vaisseau actuel.
			if(i != aShipIndex)
			{
				// Déterminer s'il y a collision avec un autre vaisseau.
				if(CommonUse.isCollision(fictionEmplacement, Protocole.getShips().get(i).getShipPlace(), deltaX, deltaY))
				{
					canMove = false;
					System.out.println("Il y a eu une collision avec un autre vaisseau");
				}
			}
		}
		
		// Si le vaisseau dépasse l'écran.
		if(!CommonUse.isInScreen(fictionEmplacement, Protocole.getScreenEmplacement(), deltaX, deltaY))
		{
			canMove = false;
			System.out.println("vous ne pouvez pas sortir de l'écran.");
		}
		
		// Si le vaisseau peut bouger.
		if(canMove)
		{
			// Bouger le vaisseau.
			Protocole.getShips().get(aShipIndex).move(deltaX, deltaY);
			Protocole.getShips().get(aShipIndex).setDirection(newDirection);
			
			System.out.println("move direction : " + Protocole.getShips().get(aShipIndex).getDirection());
			System.out.println("Position x : " + Protocole.getShips().get(aShipIndex).getShipPlace().getPosition().x);
			System.out.println("Position y : " + Protocole.getShips().get(aShipIndex).getShipPlace().getPosition().y);
			System.out.println("Position x2 : " + Protocole.getShips().get(aShipIndex).getShipPlace().getSizePosition().x);
			System.out.println("Position y2 : " + Protocole.getShips().get(aShipIndex).getShipPlace().getSizePosition().y);	
		}
		
		return workedWithoutError;
	}
}
